perm filename SPECS.RLL[RDG,DBL] blob sn#610077 filedate 1981-09-07 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00002 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00002 00002	A list of those additional values which get passed to
C00014 ENDMK
C⊗;
A list of those additional values which get passed to
	GetValue, PutValue and friends.
<<<GetField and PutField will soon have a similiar list>>>

The third arg to GetValue - "other" in most functions - is an unordered list
(actually an FSet) whose elements may be:

  (FAST-CACHE s1 s2 ... sN)  -- this causes the atom Fast-Cache to be passed
	to CacheValue, on its "why" list, for each slot, si.
  (-CACHE s1 s2 ... sN)      --  tells the get-values NOT to cache the computed
	value of any slot si.
  (-COMPUTE s1 s2 ... sN)    -- the get-values will not bother computing the
	value of any slt si; if the value isn't stored, just forget it.
  (IGNORE-CACHE s1 s2 ... sN) -- the get-values will NOT use the stored value
	of any slot si -- but rather will compute those values as needed.
  (SAFESLOT s1 s2 ... sN) -- each si really is a slot; so don't bother to 
	confirm this.
  (SAFEUNIT u1 u2 ... uN) -- each ui is really a unit.
---
[Note I am trying to adopt the convention that binary conditions be indicated
 by using some name, prefixed by + or -, depending on sense.  In general only
 one form (eg either +←←← or -←←←) will be necessary, as the other sense is
 the overall default.  For example, +CACHE is superfluous.]
---
In addition, any of these elements can be a single atom -- one of that
{FAST-CACHE -CACHE -COMPUTE IGNORE-CACHE SAFESLOT SAFEUNIT} list.
In the first 4 cases, this means the implied action will happen to every slot.
An atomic SAFE←←←← applies only to the current slot or unit.
(This might be wrong; but it did save CONS cells for the standard cases.)

I reserve the right to further elaborate this convention to suit my whims
at any later date.  For example, one may eventually want to be more specific
in determining which slot's values to, eg, ignore -- as in
   (GetValue 'Fred 'Friends '((IGNORE-CACHE AllExamples (AnyFrog AllIsas)))),
which means the cached values as U:AllExamples will be ignored for all
units U, but that V:AllIsas will be accepted EXCEPT WHEN V=AnyFrog.
I cuurently have no use for such a "feature" - do you?
Another direction may be to have forms which are evaluated during the call,
will appropriate bindings --
  (GetValue 'Fred 'Friends '((IGNORE-CACHE =Fn fn#37))),
where this fn#37 will be applied to the unit and slot being considered at
each (recursive) call to GetValue; and its values would be used as the set
of slots whose cached values should be ignored.  A slight variation of this
would be something like (... ((IGNORE-CACHE =Pred= pred#82))), where pred#82
would be a predicate whose nonNIL response meant the argument should be
"ignore-cached".  Once again, this sledge hammer may not ever be really needed,
but it has been considered.

Future directions:
(I'm sure I will need more of these values; but am waiting for a forcing
 example before implementing and documenting those options.)
(i) (USE-VALUE (u1 s1 val1) ... (uN sN vN)) meaning "pretend"
	the value of ui:si is really vali -- don't bother to compute it.
(ii) There's also some hassles when dealing with those *DO* special 
	values -- should they be treated as simple "syntactic" values, or
	"evaluated" -- ie how do I store the "value" (*DO* FSeeUnit SofU)
	as U:S?  As I said, more on this as this comes important -- unless
	you've some insights on this whole can of worms.]
-------

Onto the putting functions.
There are basically two types of values.  I'll resent the primitive ones first:
The final argument is a set of zero or more elements, each of the form

	[These apply to any of PutValue, AddValue, DeleteValue, SubstValue]
  -VERIFY -- there is no need to verify that this value is appropriate, or
	that this slot belongs on this unit.  (Yes, this may indeed be 
	confusing two distinct functions.  Eventually I worry about this,
	if I have to.)
  -INVERSES -- do NOT now add on inverse links (this is useful when this
	particular PutValue was itself adding backpointers.  If not for this
	facility that process would always lead to an infinite loop...)
  -DEPENDENCIES -- do NOT do the other miscellaneous KB updates which result
	from this modification.

	[This only applies to PutValue]
  +ALWAYS-UPDATE -- go thru the motion of adding inverse links, and other
	after-put-value functions after performing an update -- even if the 
	value seems NOT to have changed. (Ie pretend the old value was really
	RecomputeMe.)  This is needed to handle the case of unit 
	initialization, when values are first simply UA-PUTVALUEd onto the 
	unit, and later have to be actually PutValue-d.

	[These only apply to AddValue, DeleteValue, & SubstValue]
  +COMPUTE-INITIAL -- What should you do when you've been told to add on a
	new value, V, onto U:S when there is no value of U:S?
	There seem two possibilities:
	(1) do everything you can to compute the value of U:S,
	   and then add on V.
	(2) simply go on, (leaving U:S uncomputed) with the assurance that
	   any one from now on who wants
	   to find the value of U:S will specifically ask for it, using 
	   GetValue; which will now have to compute it.
	   The asssumption is that S:ToCompute will now catch this new V.
	Anyway, it turns out that both of these cases come up -- hence this
	extra parameter.
	[Note I believe the current programs will always compute the value if 
	the slot is primitive -- as this means the value is NoEntry or 
	NoEntries, depending on the format of the slot.  This is probably 
	the wrong approach...]
  N-Values -- In general one wants to add on just one value, V, to a value of
	U:S.  However there are times one may want to add a slew of {Vi} at
	once.  The purpose of this value is to distinguish these cases.
	Note this is well defined for both AddValue and DeleteValue; but
	may lead to confusion for SubstValue, if we want to replace N values
	with M values, when N <> M.  Of course we may simply bar this operation
	in general.

-------
Now for the other type of values.  First, by way of motivation, ask
why PutValue should know anything about adding inverses?  I'll
agree that DefaultPutValue should, but things at this level should be totally
invisible to the general user-level functions.  It should be sufficient
to tell PutValue that we are now AddingInverses, and nothing more.
The functions which PutValue calls, such as DefaultPutValue, should
now infer that this means not to add inverse pointers to these, ...
This implies we should pass values like AddInverse in that extra argument.
However, there are times internal functions "know" what is needed -- and
why should the other functions force them to pass these indirect values?

Solution: Allow either type to be passed.

Of course we need a table which relates those parameters with what they really
mean --
		Verify?		Inverse?	Dependencies?
New-Unit	  +  		  +
KB-Consistency					  +
AddInverse					  +
DeleteInverse					  +
RemovingForeigners				  +
UnitRenamed					  +
UnitDeleted					  +
<default>	  +		  +		  +

[Legend: the absense of a "+" means -←←←←, for parameter ←←←? above.]
This conversion takes place in Default←←←Value, 
for ←←← in {Put Add Delete Subst}.  (Inferior functions will assume they
are getting the more primitive forms.)